#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
use std::mem;
use crate::alloc_testing::*;
extern "C" {
            }
pub type size_t = libc::c_ulong;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct _HashTable {
    pub table: *mut *mut HashTableEntry,
    pub table_size: libc::c_uint,
    pub hash_func: HashTableHashFunc,
    pub equal_func: HashTableEqualFunc,
    pub key_free_func: HashTableKeyFreeFunc,
    pub value_free_func: HashTableValueFreeFunc,
    pub entries: libc::c_uint,
    pub prime_index: libc::c_uint,
}
pub type HashTableValueFreeFunc = Option::<unsafe extern "C" fn(HashTableValue) -> ()>;
pub type HashTableValue = *mut libc::c_void;
pub type HashTableKeyFreeFunc = Option::<unsafe extern "C" fn(HashTableKey) -> ()>;
pub type HashTableKey = *mut libc::c_void;
pub type HashTableEqualFunc = Option::<
    unsafe extern "C" fn(HashTableKey, HashTableKey) -> libc::c_int,
>;
pub type HashTableHashFunc = Option::<
    unsafe extern "C" fn(HashTableKey) -> libc::c_uint,
>;
pub type HashTableEntry = _HashTableEntry;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct _HashTableEntry {
    pub pair: HashTablePair,
    pub next: *mut HashTableEntry,
}
pub type HashTablePair = _HashTablePair;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct _HashTablePair {
    pub key: HashTableKey,
    pub value: HashTableValue,
}
pub type HashTable = _HashTable;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct _HashTableIterator {
    pub hash_table: *mut HashTable,
    pub next_entry: *mut HashTableEntry,
    pub next_chain: libc::c_uint,
}
pub type HashTableIterator = _HashTableIterator;
static mut hash_table_primes: [libc::c_uint; 24] = [
    193 as libc::c_int as libc::c_uint,
    389 as libc::c_int as libc::c_uint,
    769 as libc::c_int as libc::c_uint,
    1543 as libc::c_int as libc::c_uint,
    3079 as libc::c_int as libc::c_uint,
    6151 as libc::c_int as libc::c_uint,
    12289 as libc::c_int as libc::c_uint,
    24593 as libc::c_int as libc::c_uint,
    49157 as libc::c_int as libc::c_uint,
    98317 as libc::c_int as libc::c_uint,
    196613 as libc::c_int as libc::c_uint,
    393241 as libc::c_int as libc::c_uint,
    786433 as libc::c_int as libc::c_uint,
    1572869 as libc::c_int as libc::c_uint,
    3145739 as libc::c_int as libc::c_uint,
    6291469 as libc::c_int as libc::c_uint,
    12582917 as libc::c_int as libc::c_uint,
    25165843 as libc::c_int as libc::c_uint,
    50331653 as libc::c_int as libc::c_uint,
    100663319 as libc::c_int as libc::c_uint,
    201326611 as libc::c_int as libc::c_uint,
    402653189 as libc::c_int as libc::c_uint,
    805306457 as libc::c_int as libc::c_uint,
    1610612741 as libc::c_int as libc::c_uint,
];
static mut hash_table_num_primes: libc::c_uint = 0;
extern "C" fn hash_table_allocate_table(
    mut hash_table: *mut HashTable,
) -> libc::c_int {
    let mut new_table_size: libc::c_uint = 0;
    let mut boxed_hash_table = unsafe { Box::from_raw(hash_table) };

    if boxed_hash_table.prime_index < unsafe { hash_table_num_primes } {
        new_table_size = unsafe { hash_table_primes[boxed_hash_table.prime_index as usize] };
    } else {
        new_table_size = (boxed_hash_table.entries).wrapping_mul(10);
    }
    boxed_hash_table.table_size = new_table_size;
    boxed_hash_table.table = unsafe {
        alloc_test_calloc(
            boxed_hash_table.table_size as size_t,
            std::mem::size_of::<*mut HashTableEntry>() as libc::c_ulong,
        ) as *mut *mut HashTableEntry
    };

    let result = (boxed_hash_table.table != std::ptr::null_mut()) as libc::c_int;
    hash_table = Box::into_raw(boxed_hash_table);
    result
}
extern "C" fn hash_table_free_entry(
    mut hash_table: *mut HashTable,
    mut entry: *mut HashTableEntry,
) {
    let mut boxed_entry = unsafe { Box::from_raw(entry) };
    let pair = &mut boxed_entry.pair;

    if unsafe { ((*hash_table).key_free_func).is_some() } {
        unsafe {
            ((*hash_table).key_free_func).expect("non-null function pointer")((*pair).key);
        }
    }
    if unsafe { ((*hash_table).value_free_func).is_some() } {
        unsafe {
            ((*hash_table).value_free_func)
                .expect("non-null function pointer")((*pair).value);
        }
    }

    alloc_test_free(entry as *mut libc::c_void);
    let entry = Box::into_raw(boxed_entry);
}
#[no_mangle]
pub extern "C" fn hash_table_new(
    mut hash_func: HashTableHashFunc,
    mut equal_func: HashTableEqualFunc,
) -> *mut HashTable {
    let hash_table: *mut HashTable = unsafe {
        alloc_test_malloc(std::mem::size_of::<HashTable>() as libc::c_ulong) as *mut HashTable
    };
    if hash_table.is_null() {
        return std::ptr::null_mut();
    }
    let mut boxed_hash_table = unsafe { Box::from_raw(hash_table) };
    boxed_hash_table.hash_func = hash_func;
    boxed_hash_table.equal_func = equal_func;
    boxed_hash_table.key_free_func = None;
    boxed_hash_table.value_free_func = None;
    boxed_hash_table.entries = 0;
    boxed_hash_table.prime_index = 0;
    if hash_table_allocate_table(hash_table) == 0 {
        alloc_test_free(hash_table as *mut libc::c_void);
        return std::ptr::null_mut();
    }
    let hash_table = Box::into_raw(boxed_hash_table);
    hash_table
}
#[no_mangle]
pub extern "C" fn hash_table_free(mut hash_table: *mut HashTable) {
    if !hash_table.is_null() {
        let boxed_hash_table = unsafe { Box::from_raw(hash_table) };
        let mut rover: *mut HashTableEntry = std::ptr::null_mut();
        let mut next: *mut HashTableEntry = std::ptr::null_mut();
        let mut i: libc::c_uint = 0;

        while i < boxed_hash_table.table_size {
            rover = unsafe { *((boxed_hash_table.table).offset(i as isize)) };
            while !rover.is_null() {
                next = unsafe { (*rover).next };
                hash_table_free_entry(hash_table, rover);
                rover = next;
            }
            i = i.wrapping_add(1);
        }

        alloc_test_free(boxed_hash_table.table as *mut libc::c_void);
        alloc_test_free(hash_table as *mut libc::c_void);
        let hash_table = Box::into_raw(boxed_hash_table);
    }
}
#[no_mangle]
pub extern "C" fn hash_table_register_free_functions(
    hash_table: *mut HashTable,
    key_free_func: HashTableKeyFreeFunc,
    value_free_func: HashTableValueFreeFunc,
) {
    if !hash_table.is_null() {
        let mut boxed_hash_table = unsafe { Box::from_raw(hash_table) };
        boxed_hash_table.key_free_func = key_free_func;
        boxed_hash_table.value_free_func = value_free_func;
        let hash_table = Box::into_raw(boxed_hash_table);
    }
}
extern "C" fn hash_table_enlarge(mut hash_table: *mut HashTable) -> libc::c_int {
    let mut old_table: *mut *mut HashTableEntry = std::ptr::null_mut();
    let mut old_table_size: libc::c_uint = 0;
    let mut old_prime_index: libc::c_uint = 0;
    let mut rover: *mut HashTableEntry = std::ptr::null_mut();
    let mut pair: *mut HashTablePair = std::ptr::null_mut();
    let mut next: *mut HashTableEntry = std::ptr::null_mut();
    let mut index: libc::c_uint = 0;
    let mut i: libc::c_uint = 0;

    let mut boxed_hash_table = unsafe { Box::from_raw(hash_table) };
    old_table = boxed_hash_table.table;
    old_table_size = boxed_hash_table.table_size;
    old_prime_index = boxed_hash_table.prime_index;
    boxed_hash_table.prime_index = boxed_hash_table.prime_index.wrapping_add(1);
    hash_table = Box::into_raw(boxed_hash_table);

    if unsafe { hash_table_allocate_table(hash_table) } == 0 {
        let mut boxed_hash_table = unsafe { Box::from_raw(hash_table) };
        boxed_hash_table.table = old_table;
        boxed_hash_table.table_size = old_table_size;
        boxed_hash_table.prime_index = old_prime_index;
        hash_table = Box::into_raw(boxed_hash_table);
        return 0;
    }

    i = 0;
    while i < old_table_size {
        unsafe {
            rover = *old_table.add(i as usize);
        }
        while !rover.is_null() {
            unsafe {
                next = (*rover).next;
                pair = &mut (*rover).pair;
                index = (unsafe { (*hash_table).hash_func })
                    .expect("non-null function pointer")((*pair).key)
                    .wrapping_rem(unsafe { (*hash_table).table_size });
                (*rover).next = *unsafe { ((*hash_table).table).add(index as usize) };
                let ref mut fresh0 = *unsafe { ((*hash_table).table).add(index as usize) };
                *fresh0 = rover;
                rover = next;
            }
        }
        i = i.wrapping_add(1);
    }

    unsafe {
        alloc_test_free(old_table as *mut libc::c_void);
    }

    return 1;
}
#[no_mangle]
pub extern "C" fn hash_table_insert(
    mut hash_table: *mut HashTable,
    mut key: HashTableKey,
    mut value: HashTableValue,
) -> libc::c_int {
    let mut rover: *mut HashTableEntry = std::ptr::null_mut();
    let mut pair: *mut HashTablePair = std::ptr::null_mut();
    let mut newentry: *mut HashTableEntry = std::ptr::null_mut();
    let mut index: libc::c_uint = 0;

    let mut boxed_hash_table = unsafe { Box::from_raw(hash_table) };

    if (boxed_hash_table.entries).wrapping_mul(3).wrapping_div(boxed_hash_table.table_size) > 0 {
        if hash_table_enlarge(hash_table) == 0 {
            hash_table = Box::into_raw(boxed_hash_table);
            return 0;
        }
    }

    index = unsafe { (boxed_hash_table.hash_func.unwrap())(key).wrapping_rem(boxed_hash_table.table_size) };
    rover = unsafe { *boxed_hash_table.table.offset(index as isize) };

    while !rover.is_null() {
        pair = unsafe { &mut (*rover).pair };
        if unsafe { (boxed_hash_table.equal_func.unwrap())((*pair).key, key) != 0 } {
            if boxed_hash_table.value_free_func.is_some() {
                unsafe { boxed_hash_table.value_free_func.unwrap()((*pair).value) };
            }
            if boxed_hash_table.key_free_func.is_some() {
                unsafe { boxed_hash_table.key_free_func.unwrap()((*pair).key) };
            }
            unsafe {
                (*pair).key = key;
                (*pair).value = value;
            }
            hash_table = Box::into_raw(boxed_hash_table);
            return 1;
        }
        rover = unsafe { (*rover).next };
    }

    newentry = unsafe {
        alloc_test_malloc(std::mem::size_of::<HashTableEntry>() as libc::c_ulong) as *mut HashTableEntry
    };

    if newentry.is_null() {
        hash_table = Box::into_raw(boxed_hash_table);
        return 0;
    }

    unsafe {
        (*newentry).pair.key = key;
        (*newentry).pair.value = value;
        (*newentry).next = *boxed_hash_table.table.offset(index as isize);
        *boxed_hash_table.table.offset(index as isize) = newentry;
        boxed_hash_table.entries = boxed_hash_table.entries.wrapping_add(1);
    }

    hash_table = Box::into_raw(boxed_hash_table);
    return 1;
}
#[no_mangle]
pub extern "C" fn hash_table_lookup(
    mut hash_table: *mut HashTable,
    mut key: HashTableKey,
) -> HashTableValue {
    let mut rover: *mut HashTableEntry = std::ptr::null_mut();
    let mut pair: *mut HashTablePair = std::ptr::null_mut();
    let mut index: libc::c_uint = 0;

    
    unsafe {
        index = ((*hash_table).hash_func.unwrap())(key).wrapping_rem((*hash_table).table_size);
        rover = *((*hash_table).table.offset(index as isize));
    }

    while !rover.is_null() {
        
        unsafe {
            pair = &mut (*rover).pair;
            if (*hash_table).equal_func.unwrap()(key, (*pair).key) != 0 {
                return (*pair).value;
            }
            rover = (*rover).next;
        }
    }

    return std::ptr::null_mut();
}
#[no_mangle]
pub extern "C" fn hash_table_remove(
    mut hash_table: *mut HashTable,
    mut key: HashTableKey,
) -> libc::c_int {
    let mut boxed_hash_table = unsafe { Box::from_raw(hash_table) };
    let mut rover: *mut *mut HashTableEntry = std::ptr::null_mut();
    let mut entry: *mut HashTableEntry = std::ptr::null_mut();
    let mut pair: *mut HashTablePair = std::ptr::null_mut();
    let mut index: libc::c_uint = 0;
    let mut result: libc::c_int = 0;

    unsafe {
        index = (boxed_hash_table.hash_func.expect("non-null function pointer")(key))
            .wrapping_rem(boxed_hash_table.table_size);
        result = 0;
        rover = &mut *boxed_hash_table.table.offset(index as isize) as *mut *mut HashTableEntry;
        while !(*rover).is_null() {
            pair = &mut (**rover).pair;
            if boxed_hash_table.equal_func.expect("non-null function pointer")(key, (*pair).key) != 0 {
                entry = *rover;
                *rover = (*entry).next;
                hash_table_free_entry(hash_table, entry);
                boxed_hash_table.entries = boxed_hash_table.entries.wrapping_sub(1);
                result = 1;
                break;
            } else {
                rover = &mut (**rover).next;
            }
        }
    }

    hash_table = Box::into_raw(boxed_hash_table);
    result
}
#[no_mangle]
pub extern "C" fn hash_table_num_entries(
    hash_table: *mut HashTable,
) -> libc::c_uint {
    let boxed_hash_table = unsafe { Box::from_raw(hash_table) };
    let entries = boxed_hash_table.entries;
    let hash_table = Box::into_raw(boxed_hash_table);
    entries
}
#[no_mangle]
pub extern "C" fn hash_table_iterate(
    mut hash_table: *mut HashTable,
    mut iterator: *mut HashTableIterator,
) {
    let mut boxed_iterator = unsafe { Box::from_raw(iterator) };
    boxed_iterator.hash_table = hash_table;
    boxed_iterator.next_entry = std::ptr::null_mut();
    let mut chain: libc::c_uint = 0;
    while chain < unsafe { (*hash_table).table_size } {
        if !unsafe { *((*hash_table).table).offset(chain as isize) }.is_null() {
            boxed_iterator.next_entry = unsafe { *((*hash_table).table).offset(chain as isize) };
            boxed_iterator.next_chain = chain;
            break;
        } else {
            chain = chain.wrapping_add(1);
        }
    }
    let iterator = Box::into_raw(boxed_iterator);
}
#[no_mangle]
pub extern "C" fn hash_table_iter_has_more(
    mut iterator: *mut HashTableIterator,
) -> libc::c_int {
    let boxed_iterator = unsafe { Box::from_raw(iterator) };
    let result = (boxed_iterator.next_entry != std::ptr::null_mut()) as libc::c_int;
    let iterator = Box::into_raw(boxed_iterator);
    result
}
#[no_mangle]
pub extern "C" fn hash_table_iter_next(
    mut iterator: *mut HashTableIterator,
) -> HashTablePair {
    let mut current_entry: *mut HashTableEntry = std::ptr::null_mut();
    let mut hash_table: *mut HashTable = std::ptr::null_mut();
    let mut pair: HashTablePair = HashTablePair {
        key: std::ptr::null_mut(),
        value: std::ptr::null_mut(),
    };
    let mut chain: libc::c_uint = 0;

    let mut boxed_iterator = unsafe { Box::from_raw(iterator) };
    hash_table = boxed_iterator.hash_table;
    if boxed_iterator.next_entry.is_null() {
        iterator = Box::into_raw(boxed_iterator);
        return pair;
    }
    current_entry = boxed_iterator.next_entry;
    pair = unsafe { (*current_entry).pair };
    if !unsafe { (*current_entry).next }.is_null() {
        boxed_iterator.next_entry = unsafe { (*current_entry).next };
    } else {
        chain = boxed_iterator.next_chain.wrapping_add(1);
        boxed_iterator.next_entry = std::ptr::null_mut();
        while chain < unsafe { (*hash_table).table_size } {
            if !unsafe { *((*hash_table).table).offset(chain as isize) }.is_null() {
                boxed_iterator.next_entry = unsafe { *((*hash_table).table).offset(chain as isize) };
                break;
            } else {
                chain = chain.wrapping_add(1);
            }
        }
        boxed_iterator.next_chain = chain;
    }
    iterator = Box::into_raw(boxed_iterator);
    return pair;
}
extern "C" fn run_static_initializers() {
    unsafe {
        hash_table_num_primes = (std::mem::size_of::<[libc::c_uint; 24]>()
            as libc::c_ulong)
            .wrapping_div(std::mem::size_of::<libc::c_int>() as libc::c_ulong)
            as libc::c_uint;
    }
}
#[used]
#[cfg_attr(target_os = "linux", link_section = ".init_array")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XIB")]
#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
static INIT_ARRAY: [unsafe extern "C" fn(); 1] = [run_static_initializers];
